package cn.xenosp.server.module.scheduler.logs;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.xenosp.server.common.tools.IdUtil;
import cn.xenosp.server.module.scheduler.entity.ScheduledTaskLog;
import cn.xenosp.server.module.scheduler.mapper.ScheduledTaskLogMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 项目名： service-web
 * 包路径： cn.xenosp.server.module.scheduler.service
 * 作者：   TongHui
 * 创建时间: 2025-11-20 16:27
 * 描述: TODO
 * 版本: 1.0
 */
@Service
public class TaskLogService extends ServiceImpl<ScheduledTaskLogMapper,ScheduledTaskLog> {

    @Autowired
    private ConsoleLogCapture consoleLogCapture;

    // 使用内存存储日志，生产环境建议使用数据库
    private final Map<String, ScheduledTaskLog> logStore = new ConcurrentHashMap<>();
    private final int MAX_LOG_SIZE = 1000; // 最大日志数量，避免内存溢出

    /**
     * 添加执行日志
     */
    public String addLog(ScheduledTaskLog log) {
        if (log.getId() == null) {
            log.setId(IdUtil.getId());
        }
        // 限制日志数量，避免内存溢出
        if (logStore.size() >= MAX_LOG_SIZE) {
            removeOldestLogs(MAX_LOG_SIZE / 10); // 移除最旧的10%日志
        }

        logStore.put(log.getId(), log);
        baseMapper.insert(log);
        return log.getId();
    }
    /**
     * 更新日志的控制台输出
     */
    public void updateConsoleLog(String logId, String consoleLog) {
        ScheduledTaskLog log = logStore.get(logId);
        if (log != null) {
            log.setConsoleLog(consoleLog);
        }
    }
    /**
     * 获取任务的所有执行日志
     */
    public List<ScheduledTaskLog> getLogsByTaskId(String taskId) {
        return baseMapper.selectList(new LambdaQueryWrapper<>(ScheduledTaskLog.class)
                .eq(ScheduledTaskLog::getTaskId, taskId)
                .orderByDesc(ScheduledTaskLog::getCreateTime));
    }

    /**
     * 获取所有任务的执行日志
     */
    public List<ScheduledTaskLog> getAllLogs() {
        return baseMapper.getAll();
    }
    /**
     * 根据ID获取日志
     */
    public ScheduledTaskLog getLogById(String logId) {
        return baseMapper.selectById(logId);
    }
    /**
     * 根据时间范围查询日志
     */
    public List<ScheduledTaskLog> getLogsByTimeRange(Date startTime, Date endTime) {
        return logStore.values().stream()
                .filter(log -> !DateUtil.date(log.getStartTime()).isBefore(startTime) && !DateUtil.date(log.getStartTime()).isAfter(endTime))
                .sorted((l1, l2) -> l2.getStartTime().compareTo(l1.getStartTime()))
                .collect(Collectors.toList());
    }

    /**
     * 根据状态查询日志
     */
    public List<ScheduledTaskLog> getLogsByStatus(String status) {
        return logStore.values().stream()
                .filter(log -> status.equals(log.getStatus()))
                .sorted((l1, l2) -> l2.getStartTime().compareTo(l1.getStartTime()))
                .collect(Collectors.toList());
    }

    /**
     * 获取指定任务的最近N条日志
     */
    public List<ScheduledTaskLog> getRecentLogsByTaskId(String taskId, int limit) {
        return getLogsByTaskId(taskId).stream()
                .limit(limit)
                .collect(Collectors.toList());
    }

    /**
     * 删除指定任务的日志
     */
    public void deleteLogsByTaskId(String taskId) {
        List<String> logIdsToRemove = logStore.values().stream()
                .filter(log -> taskId.equals(log.getTaskId()))
                .map(ScheduledTaskLog::getId)
                .collect(Collectors.toList());

        logIdsToRemove.forEach(logStore::remove);

        baseMapper.deleteByTaskId(taskId);
    }

    /**
     * 清理过期日志
     */
    public void cleanupOldLogs(int daysToKeep) {
        Date cutoffDate =DateUtil.offsetMinute(new DateTime(), -daysToKeep);
        List<String> logIdsToRemove = logStore.values().stream()
                .filter(log -> DateUtil.date(log.getStartTime()).isBefore(cutoffDate))
                .map(ScheduledTaskLog::getId)
                .collect(Collectors.toList());

        logIdsToRemove.forEach(logStore::remove);
    }

    /**
     * 获取任务执行统计
     */
    public Map<String, Object> getTaskStatistics(String taskId) {
        List<ScheduledTaskLog> logs = getLogsByTaskId(taskId);

        long totalExecutions = logs.size();
        long successCount = logs.stream().filter(log -> "SUCCESS".equals(log.getStatus())).count();
        long failedCount = logs.stream().filter(log -> "FAILED".equals(log.getStatus())).count();

        double successRate = totalExecutions > 0 ? (double) successCount / totalExecutions * 100 : 0;
        double averageExecutionTime = logs.stream()
                .filter(log -> log.getExecutionTime() != null)
                .mapToLong(ScheduledTaskLog::getExecutionTime)
                .average()
                .orElse(0);

        Map<String, Object> stats = new HashMap<>();
        stats.put("totalExecutions", totalExecutions);
        stats.put("successCount", successCount);
        stats.put("failedCount", failedCount);
        stats.put("successRate", String.format("%.2f%%", successRate));
        stats.put("averageExecutionTime", String.format("%.2fms", averageExecutionTime));
        stats.put("lastExecution", logs.stream().findFirst().map(ScheduledTaskLog::getStartTime).orElse(null));

        return stats;
    }

    /**
     * 移除最旧的日志
     */
    private void removeOldestLogs(int count) {
        List<String> oldestLogIds = logStore.values().stream()
                .sorted(Comparator.comparing(ScheduledTaskLog::getStartTime))
                .limit(count)
                .map(ScheduledTaskLog::getId)
                .collect(Collectors.toList());

        oldestLogIds.forEach(logStore::remove);
    }
    /**
     * 获取实时控制台日志（用于正在执行的任务）
     */
    public String getRealtimeConsoleLog(String logId) {
        ScheduledTaskLog log = getLogById(logId);
        if (log != null && log.getStatus().equals("RUNNING")) {
            // 对于正在执行的任务，从捕获器中获取实时日志
            String realtimeLog = consoleLogCapture.getLogContent(logId);
            if (realtimeLog != null && !realtimeLog.isEmpty()) {
                return realtimeLog;
            }
        }
        return log != null ? log.getConsoleLog() : "";
    }
}